package com.water.component.nacos.config;

import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.config.NacosConfigService;
import com.water.wfo.component.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ByteArrayResource;

import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

/**
 * packageName com.water.component.nacos.config
 *
 * @author
 * @className NacosConfigLoader(处以class为网)
 * @date 2025/3/13
 * @description T0D0
 */
@Slf4j
public class NacosConfigLoader {

    /**
     * nacos服务地址
     */
    private static final String NACOS_CONFIG_SERVER_ADDR = "spring.cloud.nacos.config.server-addr";

    /**
     * 命名空间
     */
    private static final String NACOS_CONFIG_NAMESPACE = "spring.cloud.nacos.config.namespace";

    /**
     * 账号
     */
    private static final String NACOS_CONFIG_USERNAME = "spring.cloud.nacos.config.username";

    /**
     * 密码
     */
    private static final String NACOS_CONFIG_PD = "spring.cloud.nacos.config.password";

    /**
     * 超时时间
     */
    private static final int TIMEOUT_MS = 5000;

    /**
     * 本地缓存key
     */
    private static final String NACOS_LOCAL_CACHE_KEY = "NACOS_LOCAL_CACHE";

    /**
     * 默认map大小
     */
    private static final int DEFAULT_CACHE_SIZE = 64;

    /**
     * 缓存properties
     */
    static final LinkedHashMap<String, Properties> NACOS_LOCAL_CACHE_PROPERTIES = new LinkedHashMap<>(DEFAULT_CACHE_SIZE);

    /**
     * 缓存yaml
     */
    static final LinkedHashMap<String, String> NACOS_LOCAL_CACHE_YAML = new LinkedHashMap<>(DEFAULT_CACHE_SIZE);


    /**
     * 读取缓存中的配置
     * @return
     */
    public static final Properties getCacheProperties() {
        return NACOS_LOCAL_CACHE_PROPERTIES.get(NACOS_LOCAL_CACHE_KEY);
    }
    /**
     * 读取缓存
     * @Return java.util.Properties
     * @Date 2025/3/13 11:31
     *
     */
    public static final Properties readNacos(Properties systemProperties, NacosListService nacosListService){
        try {
            // 读取nacos yaml配置
            readNacosYaml(systemProperties, nacosListService);
        } catch (NacosException e) {
            log.error("读取nacos配置异常", e);
        }
        // yaml转换为properties
        for (Map.Entry<String, String> entry : NACOS_LOCAL_CACHE_YAML.entrySet()) {
            Properties properties = new Properties();
            parseYamlToProperties(entry.getValue(), properties);
            NACOS_LOCAL_CACHE_PROPERTIES.put(entry.getKey(), properties);
        }

        // 读取到的配置存放内存
        refreshCache();

        return NACOS_LOCAL_CACHE_PROPERTIES.get(NACOS_LOCAL_CACHE_KEY);
    }

    /**
     * 读取nacos yaml配置文件内容
     * @param systemProperties  系统配置
     * @return                  nacos yaml配置
     * @throws NacosException   读取nacos异常
     */
    static void readNacosYaml(Properties systemProperties, NacosListService nacosListService) throws NacosException {

        // 连接nacos
        NacosConfigService configService = new NacosConfigService(getNacosConfig(systemProperties));

        if(null != nacosListService) {
            String groupName = nacosListService.groupName();
            String[] dataIdList = nacosListService.dataIdList();
            for (String dataId : dataIdList) {
                // 项目公共配置
                NACOS_LOCAL_CACHE_YAML.put(dataId, configService.getConfig(dataId, groupName, TIMEOUT_MS));
                // 设置监听
                configService.addListener(dataId, groupName, new NacosListener(dataId));
            }
        }
    }

    /**
     * 更换配置
     * @param dataId
     * @param newProperties
     */
    static final void megerProperties(String dataId, Properties newProperties) {
        if (StringUtil.isNotBlank(dataId) && null != newProperties) {
            NACOS_LOCAL_CACHE_PROPERTIES.put(dataId, newProperties);
        }
    }

    /**
     * 刷新缓存
     */
    static final void refreshCache(){
        Properties allProperties = new Properties();
        for (Map.Entry<String, Properties> propertiesEntry : NACOS_LOCAL_CACHE_PROPERTIES.entrySet()) {
            if (NACOS_LOCAL_CACHE_KEY.equals(propertiesEntry.getKey())){
                continue;
            }
            for (Map.Entry<Object, Object> entry : propertiesEntry.getValue().entrySet()) {
                allProperties.put(entry.getKey(), entry.getValue());
            }
        }
        NACOS_LOCAL_CACHE_PROPERTIES.put(NACOS_LOCAL_CACHE_KEY, allProperties);
    }

    /**
     * nacos连接配置
     * @param systemProperties
     * @return
     */
    public static Properties getNacosConfig(Properties systemProperties) {
        // 连接地址
        String serverAddr = systemProperties.getProperty(NACOS_CONFIG_SERVER_ADDR);

        // 命名空间
        String namespace = systemProperties.getProperty(NACOS_CONFIG_NAMESPACE);

        // 用户名
        String username = systemProperties.getProperty(NACOS_CONFIG_USERNAME);

        // 密码
        String password = systemProperties.getProperty(NACOS_CONFIG_PD);

        // 连接参数信息
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
        properties.put(PropertyKeyConst.NAMESPACE, namespace);
        if (StringUtil.isNotBlank(username)) {
            properties.put(PropertyKeyConst.USERNAME, username);
        }
        if (StringUtil.isNotBlank(password)) {
            properties.put(PropertyKeyConst.PASSWORD, password);
        }
        return properties;
    }

    /**
     * yaml内容copy转换为properties
     *
     * @param yamlContentSource       源配置
     * @param nacosPropertiesTarget   目标配置
     * @return
     */
    static void parseYamlToProperties(String yamlContentSource, Properties nacosPropertiesTarget){
        // 源为空，则不copy
        if (StringUtil.isBlank(yamlContentSource)) {
            return;
        }

        // 读取yaml内容
        YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
        ByteArrayResource byteArrayResource = new ByteArrayResource(yamlContentSource.getBytes(StandardCharsets.UTF_8));
        yaml.setResources(byteArrayResource);

        // yaml copy到properties
        Properties yamlProperties = yaml.getObject();
        if(null != yamlProperties) {
            for (Map.Entry<Object, Object> entry : yamlProperties.entrySet()) {
                nacosPropertiesTarget.setProperty(entry.getKey().toString(), entry.getValue().toString());
            }
        }
    }
}
